/**
 * 
 */
package gui.controller;

import engine.ExternalSource;
import engine.Service;
import gui.view.EngineMain;
import gui.view.source.SourceLeftPanel;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;

import javax.swing.JOptionPane;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

import massDistribution.MeasuredAttribute;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * @author Elisa Costante
 * 
 */
public class SourceLeftListener implements ActionListener, TableModelListener {

	private SourceLeftPanel leftPanel;
	private EngineMain frame;

	public SourceLeftListener(SourceLeftPanel leftPanel, EngineMain frame) {
		this.leftPanel = leftPanel;
		this.frame = frame;
	}

	/**
	 * This is the listener for the changhing in the sourceName
	 * 
	 * @seejavax.swing.event.TableModelListener#tableChanged(javax.swing.event. 
	 *                                                                          TableModelEvent
	 *                                                                          )
	 */
	@Override
	public void tableChanged(TableModelEvent e) {
		// int row = e.getFirstRow();
		// int column = e.getColumn();
		// TableModel model = (TableModel) e.getSource();
		// String columnName = model.getColumnName(column);
		// if (columnName.equalsIgnoreCase("Name")) {
		// String id = (String) model.getValueAt(row, 0);
		// String newSourceName = (String) model.getValueAt(row, column);
		// if (sourcesList != null) {
		// Service source = sourcesList.get(id);
		// if (source != null) {
		// source.setIdentifierName(newSourceName);
		// updateSourceList();
		// }
		// }
		//
		// }

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().equalsIgnoreCase("numberOfSource")) {
			changeSourcesTable(false);
		} else if (e.getActionCommand().equalsIgnoreCase("load")) {
			loadAction();

		} else if (e.getActionCommand().equalsIgnoreCase("save")) {
			if (isPossibleToSave()) {
				// Read the name of the sources just in case they have been
				// modified.
				TableModel tableModel = leftPanel.getSourcesTableModel();
				if (frame.getSourceList() != null
						&& frame.getSourceList().size() > 0) {
					for (int rowIndex = 0; rowIndex < tableModel.getRowCount(); rowIndex++) {
						String previousName = (String) tableModel.getValueAt(
								rowIndex, 0);
						String newName = (String) tableModel.getValueAt(
								rowIndex, 1);
						if (newName != null && !newName.equals("")
								&& !newName.equalsIgnoreCase(previousName)) {
							ExternalSource source = frame
									.getSourceFromName(previousName);
							if (source != null)
								source.setIdentifierName(newName);
						}

					}

				}
				// Start to write in to the file.
				saveAction();
			} else {
				JOptionPane.showMessageDialog(leftPanel,
						"You must show generated data before to save");
			}

		}

	}

	/**
	 * @return true if and only if the values of attributes for the services
	 *         have been already generated, false otherwise;
	 */
	private boolean isPossibleToSave() {
		if (frame.getSourceList() != null) {
			for (ExternalSource externalSource : frame.getSourceList()) {
				if (externalSource.getMeasuredServices() != null) {
					for (Service service : externalSource.getMeasuredServices()) {

						if (service.getMeasuredAttributes() != null) {
							for (MeasuredAttribute attribute : service
									.getMeasuredAttributes()) {
								if (attribute.getMetric().getMeasure() == null
										|| attribute.getMetric().getMeasure()
												.getValue() == null)
									return false;
							}
						}

					}
				}
			}

		}
		return true;
	}

	/**
	 * 
	 */
	private void saveAction() {
		File fileChoose = CustomizedFileChooser.getFileToSave(leftPanel);
		if (fileChoose != null) {
			saveSourcesSettingsInXMLFile(fileChoose);
			JOptionPane
					.showMessageDialog(leftPanel, "File saved with success!");

		} else {
			JOptionPane.showMessageDialog(leftPanel,
					"Save action not accomplished correctly");
		}
	}

	/**
	 * @param fileChoose
	 */
	private void saveSourcesSettingsInXMLFile(File fileChoose) {
		XStream xs = new XStream();

		// Write to a file in the file system
		try {
			FileOutputStream fs = new FileOutputStream(fileChoose);
			xs.toXML(frame.getSourceList(), fs);
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}

	}

	/**
	 * 
	 */
	private void loadAction() {
		File fileChoose = CustomizedFileChooser.getFileToOpen(leftPanel);
		if (fileChoose != null) {
			loadSourcesSettingsFromXMLFile(fileChoose);
		} else {
			JOptionPane.showMessageDialog(leftPanel, "Load not accomplished");
		}

	}

	/**
	 * @param fileChoose
	 */
	@SuppressWarnings("unchecked")
	private void loadSourcesSettingsFromXMLFile(File fileChoose) {
		XStream xs = new XStream(new DomDriver());
		// sourcesList = new Hashtable<String, ExternalSource>();
		ArrayList<ExternalSource> sourceList = new ArrayList<ExternalSource>();

		try {
			FileInputStream fis = new FileInputStream(fileChoose);
			sourceList = (ArrayList<ExternalSource>) xs.fromXML(fis);
			frame.setSourceList(sourceList);

			// shows the sources
			changeSourcesTable(true);

		} catch (FileNotFoundException ex) {
			ex.printStackTrace();
		}

	}

	/**
	 * Set the left panel in order to show the sources
	 * 
	 * @param fromFile
	 *            : true if the sources are loaded from file, false otherwise
	 * 
	 */
	private void changeSourcesTable(boolean fromFile) {
		if (fromFile) {

			DefaultTableModel tableModel = leftPanel.getSourcesTableModel();

			ArrayList<ExternalSource> allSourcesArray = frame.getSourceList();

			tableModel.setRowCount(allSourcesArray.size());

			for (int i = 0; i < allSourcesArray.size(); i++) {
				tableModel.setValueAt(allSourcesArray.get(i)
						.getIdentifierName(), i, 0);
				tableModel.setValueAt("", i, 1);
			}

		} else {
			int n = (Integer) leftPanel.getNumberOfSourcesCombo()
					.getSelectedItem();
			ArrayList<ExternalSource> sourceList = new ArrayList<ExternalSource>(
					n);
			// Set n sources

			DefaultTableModel tableModel = leftPanel.getSourcesTableModel();
			tableModel.setRowCount(n);
			for (int i = 0; i < n; i++) {
				tableModel.setValueAt("Source" + (i + 1), i, 0);
				tableModel.setValueAt("", i, 1);
				ExternalSource source = new ExternalSource("Source" + (i + 1));
				if (frame.getSourceList() == null) {
					frame.setSourceList(new ArrayList<ExternalSource>());
				}
				sourceList.add(source);
			}
			frame.setSourceList(sourceList);

		}

	}

}
